

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import java.text.DecimalFormat;
import java.text.NumberFormat;

import java.util.Arrays;
import java.util.Date;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import Survey.*;

@SuppressWarnings("unused")
public class Client {

	Socket server = null;
	ObjectInputStream in = null;
	ObjectOutputStream out = null;
	Instructions instr;
	Pledge data;
	ClientInfo cinfo;
	MainGui maingui;
	Vector<SurveyParameters> surveys;
	
	static int round = 1;
	static int maxround = 1;
	static double A;
	static double B;
	static double alpha;
	static double endowed;

	public Client(Socket s) {
		server = s;
		try {
			out = new ObjectOutputStream(server.getOutputStream());
			in = new ObjectInputStream(server.getInputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
		cinfo = new ClientInfo(null);
		String answer = (String) JOptionPane.showInputDialog(null,
				"Please enter your ID number: ", "Enter ID",
				JOptionPane.INFORMATION_MESSAGE, null, null, null);
		try {
			cinfo.subjectNumber = answer;
		} catch (NumberFormatException e) {
			System.err.println(e.getMessage());
		}
		SendData sd = new SendData(out,
				new Vector<Object>(Arrays.asList(cinfo)));
		sd.start();
	}

	public static void main(String[] args) {

		// the ip address given for the server
		InetAddress ip = null;
		
		Socket server = null;
		Client client;

		String warning = "";
		// connect to server
		while (ip == null) {
			try {
				//set up connection
				String result = (String) JOptionPane.showInputDialog(null,
						warning + "Please enter IP of Server: ",
						"Enter Server IP Address:",
						JOptionPane.INFORMATION_MESSAGE, null, null, null);
				
				//set up our individual pledge
				String endowedStr = (String) JOptionPane.showInputDialog(null,
						warning + "How much were you endowed with?",
						"How much were you endowed with?",
						JOptionPane.INFORMATION_MESSAGE, null, null, null);
				endowed = new Double(endowedStr);
				
				if (result == null) {
					System.exit(0);
				}

				ip = InetAddress.getByName(result);
				server = new Socket(ip, 4443);
			} catch (Exception ex) {
				ip = null;
				warning = "Invalid IP \n";
			}
		}

		client = new Client(server);
		client.grabData();
		client.startListening();
		client.instr = new Instructions(client);
	}
	
	//BUG -- need to fetch data before instructions
	public void grabData() {
		try {
			A = (Double) in.readObject();
			B = (Double) in.readObject(); /*incoming survey will be null*/
			alpha = (Double) in.readObject();
			maxround = (Integer) in.readObject();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void startDecisionMaker() {
		/* added by me
		try {
			gambles = (Gamble[]) in.readObject();
			surveys = (Vector<SurveyParameters>)in.readObject(); /*incoming survey will be null*//*
			order = ((Integer) in.readObject()).intValue();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}*/
		
		
		//if we're continuing a session, load it from the downloaded clientInfo
		if(cinfo.roundNum > 1)
		{
			this.data = cinfo.pledge;
			round = cinfo.roundNum;
		}
		//this is a fresh cinfo we are dealing with
		else
		{
			Pledge p = new Pledge(0,0,endowed,cinfo.index);
			this.data = p;
			data.payout = Client.B;
			cinfo.guiIndex = cinfo.index;
			cinfo.attachPledge(p);
		}
		
		cinfo.setStatus(Pledge.STAGE1_WORKING);
		SendData sd = new SendData(out, new Vector<Object>(Arrays
				.asList(new Integer(Pledge.STAGE1_WORKING))));
		sd.start();

//		cinfo.choices = new double[1][8];
//		for (int i = 0; i < cinfo.choices.length; i++) {
//			cinfo.choices[i][0] = 0;
//		}
		
		maingui = new MainGui(data, A, B, alpha, this);
		maingui.setVisible(true);
	}

	public void startListening() {
		GetParameters gp = new GetParameters(in, this);
		gp.start();
	}

	public void update(int[] message) {
		cinfo.setStatus(message[0]);
		//System.out.println("Message: " + message[0] + " " + message[1] + " " + message[2]);

		switch (message[0]) {

/*		case Gamble.STAGE1_WORKING:
			break;*/
		case Pledge.STAGE1_DONE:
			SendData sd = new SendData(out, data);
			sd.start();
			break;

		case Pledge.DONE:
			
			int option, i;

			SendData sd1 = new SendData(out, data);
			sd1.start();

//			chosenNumber = message[1]-1; /*which Gamble is the one that counts*/
					
/*			for(int a = 0; a < cinfo.choices.length; a++){
				for(int b = 0; b < cinfo.choices[a].length; b++){
					System.out.print(" " + cinfo.choices[a][b]);
				}
				System.out.println();
			}*/
			
//			option = cinfo.choices[(chosenNumber)][1]; 

			//System.out.println("Option: " + option);
			
//			for (i = 0; i < pledges.length; i++) {
//				System.out.println(pledges[i].index);
////				if (pledges[i].index == (chosenNumber)) {
////					break;
////				}
//			}
			
			//System.out.println("Percentage" + message[2]);
			
			double amount = -1;
//			if (message[2] <= option) {
//				amount += (gambles[i].getMaxY() - option) * gambles[i].getPerCent();				
//			} 
			
			cinfo.payment = amount;

			NumberFormat moneyFormat = NumberFormat.getCurrencyInstance();

			maingui.messages
					.setText("<html><font size=+1 align=\"center\">Thank you for participating. You earned a $10.00 thank you payment plus "
							+ moneyFormat.format(amount-10) + " in gains, for total earnings of " + moneyFormat.format(amount) + "."
							+ " <p><p>While we are preparing your payments, please answer a few questions about today's study.<p><p>"
							+ "Your honest answers will greatly improve our research.<p> Thank you very much.</font></html>");

			maingui.body2.setText("Thank you for Participating.");
			maingui.bottom.removeAll();

			maingui.next
					.removeActionListener(maingui.next.getActionListeners()[0]);
			
			maingui.next.setText("");
			maingui.next.setEnabled(false);
			maingui.bottom.add(maingui.next);
			maingui.bottom.validate();
			maingui.bottom.repaint();
			maingui.gamblePanel.validate();
			maingui.gamblePanel.repaint();
			maingui.validate();
			maingui.repaint();
			break;
		}
	}
	
	public void setupNextRound() {
		if(Client.round >= Client.maxround)
		{
			NumberFormat formatter = new DecimalFormat("#0.00");
			JLabel jl = new JLabel("<html><center><font size=6><p>The game is over!</p>" +
					"<p></p><p>Your total giving: $E "+formatter.format(data.given)+
					"</p><p></p><p>All total giving: $E "+formatter.format(data.othersTotalGiven)
					+"</p><p></p><p>Your payoff: $US "+formatter.format(data.payout)+"</p></font></center></html>");
			jl.setHorizontalAlignment(JLabel.CENTER);
			jl.setAlignmentX(Component.CENTER_ALIGNMENT);
			cinfo.attachPledge(data);
			Client.round++;
			maingui.gamblePanel.add(jl, BorderLayout.CENTER);
			maingui.validate();
			maingui.repaint();
		}
		else
		{
			//attach the pledge to clientInfo
			cinfo.attachPledge(data);
			Client.round++;
			RoundPane pledgePane = new RoundPane(data, 5000, Client.A, Client.B, Client.alpha, Client.round);
			maingui.gamblePanel.add(pledgePane, BorderLayout.CENTER);
			maingui.body2.setText("<html><center>INDEX = "+ data.index +" Please be sure to select gamble you like MOST on this page before clicking Next.<p>You will not have a chance to go back.</center></html>");
			maingui.next.setEnabled(true);
			maingui.time = new Date().getTime();
			maingui.validate();
			maingui.repaint();
		}
	}



/******************************************************************************
 *gets the gambles and parameters
 ******************************************************************************/
class GetParameters extends Thread {

	ObjectInputStream in;
	Client client;

	public GetParameters(ObjectInputStream in, Client client) {
		this.in = in;
		this.client = client;
	}

	public void run() {

		Object temp;
		try {
			// start listening
			while (null != (temp = in.readObject())) {
				if(Pledge.class.isInstance(temp)) {	
					//set data to the new pledge
					client.data = (Pledge) temp;
					
					//zero out the values
					client.data.x = 0;
					client.data.ratio = 0;
					client.data.y = 0;
					System.err.println("It read in a Pledge! "+ data.index + " " + data.given);
					
					//set up GUI
					client.setupNextRound();
					
				} else if (ClientInfo.class.isInstance(temp)) {
					//THIS HAPPENS IF YOU TRY TO RECONNECT A DROPPED CLIENT
					System.err.println("Recieved ClientInfo!");
					client.cinfo = (ClientInfo) temp;
					client.data = client.cinfo.pledge;
					client.data.x = 0;
					client.data.ratio = 0;
					client.data.y = 0;
					System.err.println("Cinfo and Pledge indexes: "+cinfo.index + " and " + cinfo.pledge.index);
					
				} else if (Integer.class.isInstance(temp)) {
					System.err.println("Client "+client.cinfo.subjectNumber+"'s index set to: "+temp);
					client.cinfo.index = (Integer) temp;
					client.cinfo.oldIndex = (Integer) temp;
					if(!client.cinfo.existed) client.cinfo.guiIndex = (Integer) temp;
				} else if (int[].class.isInstance(temp)) {
					client.update((int[]) temp);
				} else if (String.class.isInstance(temp)
						&& ((String) temp).equals("close")) {
					System.exit(0);
				}
			}
		} catch (EOFException e) {
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}


}